<?php
set_include_path("../include;include");
require_once '/util/helperFunctions.php';
require_once 'Event.php';
require_once 'Entry.php';
require_once 'CodeKeeper.php';
require_once '/dao/RegistrationDAO.php';

class Registration {
	private $id;
	private $event;
	private $email;
	private $code;
	private $payed;
	private $totalCost;
	private $dateTime;
	private $responsibleName;
	

	private $entries;

	public function __construct(Event $event) {
		$this->event = $event;
		$this->entries = array();
	}

	/**
	 * Static constructor function with fields as arguments
	 * @param $event The event which this registration is for
	 * @param $email The email address of the responsible for this registration
	 * @param $code The generated code to reference this registration
	 * @param $payed Is the registration payed yet
	 * @param $totalCost The total cost of the registration
	 * @param $dateTime The datetime on which the registration has been submitted
	 */
	public static function createNew(Event $event, string $email, string $code, boolean $payed, double $totalCost, integer $dateTime, string $responsibleName) {
		$instance = new self($event);
		$instance->email = $email;
		$instance->code = $code;
		$instance->payed = $payed;
		$instance->totalCost = $totalCost;
		$instance->dateTime = $dateTime;
		$instance->responsibleName = $responsibleName;
		return $instance;
	}

	/**
	 * Saves this Registration.
	 * @return integer The id of this Registration
	 */
	public function save() {
		$dao = RegistrationDAO::getInstance();

		//Generate code, and save again
		if (!isset($this->code)) {
			$this->code = CodeKeeper::generateCode($this->event);
		}
		
		$this->totalCost = $this->calculateTotalCost();

		//shouldn't be needed: $this->event->save();
		$myid = $dao->save($this);
		$this->id = $myid;

		// save all added entries!!
		foreach ($this->entries as $entry) {
			$entry->save();
		}

		return $myid;
	}
	
	public function saveIsPayed() {
		$dao = RegistrationDAO::getInstance();
		$dao->saveIsPayed($this);
	}
	
	private function calculateTotalCost() {
		$totalcost = (double) 0.0;
		foreach ($this->entries as $entry) {
			$price = $entry->getPriceCategory()->getCost();
			$suppls = $entry->getSupplements();
			
			// Normal price for this category
			$totalcost += $price;
			
			foreach ($suppls as $supp) {
				$suppPrice = $supp->getPrice();
				
				// Extra supplement (can be negative too)
				$totalcost += $suppPrice;
			}
		}
		return $totalcost;
	}
	
	

	/**
	 * Loads this Registration with all the fields corresponsing with the given id.
	 * @param integer $id The id to which the loaded fields shouls correspond
	 */
	public function load(integer $id) {
		$dao = RegistrationDAO::getInstance();

		$this->id = $id;
		$this->event = Event::loadEvent($dao->getEventByRegistrationId($id));
		$this->email = $dao->getEmailtByemailId($id);
		$this->code = $dao->getCodeByRegistrationId($id);
		$this->payed = $dao->getIsPayedByRegistrationId($id);
		$this->totalCost = $dao->getTotalCostByRegistrationId($id);
		$this->dateTime = $dao->getDateTimeByRegistrationId($id);
		$this->responsibleName = getResponsibleNameByRegistrationId($id);
		
		//populate entries
		$this->entries = self::createEntriesArray($this);
	}

	/**
	 * Static save method, to save a Registration object from somwhere else.
	 * @param Registration $registration The Registration that is to be saved
	 */
	public static function saveRegistration(Registration $registration) {
		$dao = RegistrationDAO::getInstance();

		//Generate code, and save again
		$this->code = CodeKeeper::generateCode($this->event);

		$reg_id = $dao->save($registration);
		$registration->id = $reg_id;

		//save all added entries!!
		foreach ($this->entries as $entry) {
			$entry->save();
		}

		return $reg_id;
	}

	/**
	 * Static load method, to load an existing Registration object from somewhere else, using its id.
	 * @param integer $id The unique id of the Registration
	 */
	public static function loadRegistration(integer $id) {
		$dao = RegistrationDAO::getInstance();
		$ev = Event::loadEvent($dao->getEventIdByRegistrationId($id));
		$reg = new self($ev);

		$reg->id = $id;
		$reg->email = $dao->getEmailByRegistrationId($id);
		$reg->code = $dao->getCodeByRegistrationId($id);
		$reg->payed = $dao->getIsPayedByRegistrationId($id);
		$reg->totalCost = $dao->getTotalCostByRegistrationId($id);
		$reg->dateTime = $dao->getDateTimeByRegistrationId($id);
		$reg->responsibleName = $dao->getResponsibleNameByRegistrationId($id);

		//populate entries
		$reg->entries = self::createEntriesArray($reg);

		return $reg;
	}
	
	/**
	 * Get all registrations of a certain Event.
	 * @param Event $event The event to get the registrations for
	 * @return An array of Registration objects
	 */
	public static function getAllRegistrations(Event $event) {
		$dao = RegistrationDAO::getInstance();
		
		$regs = $dao->getRegistrationsByEvent($event);
		return $regs;
	}

	/**
	 * Load a Registration object by giving the unique code.
	 * @param string $code The unique code
	 * @return A Registration object
	 */
	public static function loadRegistrationByCode(string $code) {
		$dao = RegistrationDAO::getInstance();

		$registration = $dao->getRegistrationByCode($code);
		$registration->entries = self::createEntriesArray($registration);
		return $registration;
	}

	private static function createEntriesArray(Registration $registration) {
		$participants = Participant::getAllParticipantsFor($registration);
		$entries = array();
		foreach ($participants as $part) {
			$entries[] = Entry::load($registration, $part);
		}
		return (array) $entries;
	}

	//TODO are you sure you need this?
	public static function getRegistrationFor(Event $event, Participant $participant) {
		$dao = RegistrationDAO::getInstance();
		return $dao->getRegistrationFor($event->getId(), $participant->getId());
	}


	/* Utility methods */
	/**
	 * Create a new participant for this registration. This object hasn't been saved yet!
	 * @return A new Participant object, with its registration field pre-filled in.
	 */
	public function newEntry() {
		$entry = new Entry($this);
		$this->entries[] = $entry;
		return $entry;
	}

	public function removeEntry(Entry $entry) {
		//TODO implement ??
	}

	/**
	 * Returns all Participant objects of this Registration object as an array.
	 * @return An array of Participant objects
	 */
	public function getEntries() {
		return (array) $this->entries;
	}

	/* Getters ands setters */

	public function getId() {
		return $this->id;
	}

	public function setId($id) {
		$this->id = $id;
	}


	/**
	 * Returns the event
	 *
	 * @return Event
	 */
	public function getEvent()
	{
		return $this->event;
	}

	public function setEvent(Event $event) {
		$this->event = $event;
	}

	/**
	 * Returns the email
	 *
	 * @return string
	 */
	public function getEmail()
	{
		return $this->email;
	}

	public function setEmail(string $email) {
		$this->email = $email;
	}

	/**
	 * Returns the code
	 *
	 * @return string
	 */
	public function getCode()
	{
		return $this->code;
	}

	public function setCode(string $code) {
		$this->code = $code;
	}

	/**
	 * Returns if an payment has been received
	 *
	 * @return boolean
	 */
	public function isPayed()
	{
		return (boolean) $this->payed;
	}

	public function setPayed(boolean $payed) {
		$this->payed = $payed;
	}

	/**
	 * Returns the total cost
	 *
	 * @return double
	 */
	public function getTotalCost()
	{
		return $this->totalCost;
	}

	public function setTotalCost(integer $totalCost) {
		$this->totalCost = $totalCost;
	}

	/**
	 * Returns the timestamp
	 *
	 * @return timestamp
	 */
	public function getDateTime()
	{
		return $this->dateTime;
	}

	public function setDateTime(integer $timestamp) {
		$this->dateTime = $timestamp;
	}
	
	public function getResponsibleName() {
		return $this->responsibleName;
	}
	
	public function setResponsibleName($responsibleName) {
		$this->responsibleName = $responsibleName;
	}	

	public function __toString() {
		$betaald = $this->isPayed() ? "" : "NOG NIET BETAALD";
		return "Registratie voor " . $this->getEvent() . " van ".$this->email.". (&euro;" . $this->getTotalCost()." $betaald)";
	}
}